package com.arpa.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.cache.*;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.ShipmentWarehouseValidate;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.ntocc.common.domain.entity.Shipment;
import com.arpa.ntocc.common.service.IShipmentService;
import com.arpa.wms.cache.*;
import com.arpa.wms.common.util.OrderIdGeneratorUtil;
import com.arpa.wms.domain.consts.CommonConst;
import com.arpa.wms.domain.dto.DamagedDTO;
import com.arpa.wms.domain.dto.DamagedExcelDTO;
import com.arpa.wms.domain.dto.DamagedItemDTO;
import com.arpa.wms.domain.dto.GoodsUnitConversionDTO;
import com.arpa.wms.domain.entity.*;
import com.arpa.wms.domain.enums.DamagedStatusEnum;
import com.arpa.wms.domain.enums.DeliveryStatusEnum;
import com.arpa.wms.domain.enums.DeliveryTypeEnum;
import com.arpa.wms.domain.enums.StatusEnum;
import com.arpa.wms.domain.vo.DamagedItemVO;
import com.arpa.wms.domain.vo.DamagedVO;
import com.arpa.wms.domain.vo.GoodsUnitConversionVO;
import com.arpa.wms.mapper.DamagedMapper;
import com.arpa.wms.service.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static com.arpa.wms.domain.consts.CodeConst.*;
import static com.arpa.wms.domain.consts.CommonConst.*;
import static com.arpa.wms.domain.consts.NumConst.*;
import static com.arpa.wms.domain.consts.TipConst.*;

/**
 * <p>
 * 破损单 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-08-20
 */
@Service
@Log4j2
public class DamagedServiceImpl extends ServiceImpl<DamagedMapper, Damaged> implements IDamagedService {

    @Autowired
    private ShipmentCache shipmentCache;
    @Autowired
    private WarehouseCache warehouseCache;

    @Autowired
    private PartyCache partyCache;
    @Autowired
    private IDamagedItemService iDamagedItemService;

    @Autowired
    private IDeliveryService iDeliveryService;
    @Autowired
    private IGoodsUnitConversionService goodsUnitConversionService;

    @Autowired
    private IDeliveryItemService iDeliveryItemService;
    @Autowired
    private UnitCache unitCache;
    @Autowired
    private GoodsCache goodsCache;
    @Autowired
    private DictCache dictCache;
    @Autowired
    private WarehouseShipmentCache warehouseShipmentCache;
    @Autowired
    private DamagedCache damagedCache;
    @Autowired
    private GoodsUnitConversionCache goodsUnitConversionCache;
    @Autowired
    private IShipmentService shipmentService;
    @Autowired
    private PartyGroupCache partyGroupCache;

    /**
     * 保存
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean save(Damaged entity) {
        if (StringUtils.isBlank(entity.getCode())) {
            entity.setCode(OrderIdGeneratorUtil.generatorOrderId(OrderIdGeneratorUtil.OrderTypeEnum.BS, "",UserUtil.getBranchCode()));
            entity.setGroupCode(UserUtil.getBranchCode());
            entity.setWarehouseName(warehouseCache.translate(entity.getWarehouseCode()));
            entity.setShipmentName(shipmentCache.translate(entity.getShipmentCode()));
        }
        if (StringUtils.isBlank(entity.getCreatedBy())) {
            entity.setCreatedBy(UserUtil.getCode());
            entity.setCreatedName(partyCache.translate(UserUtil.getCode()));
        }
        entity.setModifiedBy(UserUtil.getCode());
        entity.setModifiedName(partyCache.translate(UserUtil.getCode()));

        this.saveItem(entity);
        BigDecimal totalUnitQuantity = entity.getDamagedItemList().stream().map(DamagedItem::getUnitQuantity).reduce(BigDecimal::add).get();
        entity.setTotalUnitQuantity(totalUnitQuantity);
        BigDecimal totalQuantity = entity.getDamagedItemList().stream().map(DamagedItem::getQuantity).reduce(BigDecimal::add).get();
        entity.setTotalQuantity(totalQuantity);
        return super.save(entity);
    }

    /**
     * 根据code更新实体
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public int updateByCode(Damaged entity) {
        entity.setWarehouseName(warehouseCache.translate(entity.getWarehouseCode()));
        entity.setShipmentName(shipmentCache.translate(entity.getShipmentCode()));
        if (StringUtils.isBlank(entity.getModifiedBy())) {
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
        }

        List<String> deleteCodes = entity.getDeleteCodes();
        if (IterUtil.isNotEmpty(deleteCodes)) {
            iDamagedItemService.remove(new QueryWrapper<DamagedItem>().lambda().in(DamagedItem::getCode, deleteCodes).eq(DamagedItem::getGroupCode,UserUtil.getBranchCode()));
        }
        //保存明细
        this.saveItem(entity);
        BigDecimal totalUnitQuantity = entity.getDamagedItemList().stream().map(DamagedItem::getUnitQuantity).reduce(BigDecimal::add).get();
        BigDecimal totalQuantity = entity.getDamagedItemList().stream().map(DamagedItem::getQuantity).reduce(BigDecimal::add).get();
        entity.setTotalQuantity(totalQuantity);
        entity.setTotalUnitQuantity(totalUnitQuantity);

        return baseMapper.update(entity, new QueryWrapper<Damaged>().lambda().eq(Damaged::getCode, entity.getCode()).eq(Damaged::getGroupCode,UserUtil.getBranchCode()));
    }

    /**
     * 查询列表
     *
     * @param damagedDTO
     * @return
     */
    @Override
    public List<DamagedVO> queryList(DamagedDTO damagedDTO) {
        //排序字段名需要驼峰转数据库下划线类型字段名
        if (StringUtils.isNotEmpty(damagedDTO.getSortField())) {
            damagedDTO.setSortField(CommonUtil.camel2Underline(damagedDTO.getSortField()));
        }
        List<DamagedVO> damagedVOList = baseMapper.queryList(damagedDTO);
        return damagedVOList;
    }

    /**
     * 查询合计,包含总数
     *
     * @param damagedDTO
     * @return
     */
    @Override
    public DamagedVO queryListSum(DamagedDTO damagedDTO) {
        DamagedVO damagedVO = baseMapper.queryListSum(damagedDTO);
        return damagedVO;
    }


    /**
     * 批量删除
     *
     * @param codes
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void batchdel(List<String> codes) {
        for (String code : codes) {
            this.update(new UpdateWrapper<Damaged>().lambda().eq(Damaged::getCode, code).eq(Damaged::getGroupCode,UserUtil.getBranchCode())
                    .set(Damaged::getDeleted, 1));
        }
    }

    /**
     * 作废
     * <p>
     * 0 新增 1待审核 2审核通过 3 驳回 4作废
     *
     * @param code
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Result blank(String code) {
        Damaged damaged = this.getOne(new QueryWrapper<Damaged>().lambda().eq(Damaged::getCode, code).eq(Damaged::getGroupCode,UserUtil.getBranchCode()));
        if (damaged != null) {
            //作废报损单；
            this.update(new UpdateWrapper<Damaged>().lambda().eq(Damaged::getCode, code).eq(Damaged::getDeleted, 0).eq(Damaged::getGroupCode,UserUtil.getBranchCode())
                    .set(Damaged::getStatus, DamagedStatusEnum.INVALID.getValue()));
            return Result.ok("作废成功");

        } else {
            return Result.error("作废失败，报损单不存在");
        }
    }

    /**
     * 获取详情
     *
     * @param code code
     * @return
     */
    @Override
    public DamagedVO getVoByCode(String code) {
        Damaged damaged = getOne(new QueryWrapper<Damaged>().lambda().eq(Damaged::getCode, code).eq(Damaged::getGroupCode,UserUtil.getBranchCode()));
        if (ObjectUtil.isNull(damaged)) {
            log.error("报损单【{}】不存在", code);
            throw new ServiceException("报损单【 " + code + "】不存在！");
        }

        DamagedVO damagedVO = new DamagedVO();
        BeanUtils.copyProperties(damaged, damagedVO);

        damagedVO.setWarehouseName(warehouseCache.translate(damagedVO.getWarehouseCode()));
        damagedVO.setShipmentName(shipmentCache.translate(damagedVO.getShipmentCode()));
        damagedVO.setGroupName(partyGroupCache.translate(damagedVO.getGroupCode()));

        DamagedItemDTO damagedItemDTO = new DamagedItemDTO();
        damagedItemDTO.setDamagedCode(code);
        damagedItemDTO.setPageSize(Integer.MAX_VALUE);

        //获取收货单明细信息
        List<DamagedItemVO> damagedItemVOList = this.iDamagedItemService.queryList(damagedItemDTO);

        GoodsUnitConversionDTO goodsUnitConversionDTO = new GoodsUnitConversionDTO();
        goodsUnitConversionDTO.setPageSize(Integer.MAX_VALUE);
        goodsUnitConversionDTO.setGroupCode(UserUtil.getBranchCode());
        List<GoodsUnitConversionVO> goodsUnitConversionList = goodsUnitConversionService.queryList(goodsUnitConversionDTO);

        damagedItemVOList.stream().forEach(item -> {
            item.setShipmentName(damagedVO.getShipmentName());
            List<GoodsUnitConversionVO> goodsUnitConversionVOList = Lists.newArrayList();
            goodsUnitConversionList.stream().forEach(goodsUnitConversionVO -> {
                if (goodsUnitConversionVO.getGoodsCode().equals(item.getGoodsCode())) {
                    goodsUnitConversionVOList.add(goodsUnitConversionVO);
                }
            });
            item.setGoodsUnitConversionList(goodsUnitConversionVOList);
        });


        damagedVO.setDamagedItemList(damagedItemVOList);
        return damagedVO;
    }


    /**
     * 审核
     * <p>
     * 0 新增 1待审核 2审核通过 3 驳回 4作废
     *
     * @param damaged
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Result audit(Damaged damaged) {
        //先审核
        damaged.setGmtApproved(LocalDateTime.now());
        damaged.setApprovedBy(UserUtil.getCode());
        damaged.setApprovedName(partyCache.translate(UserUtil.getCode()));
        damaged.setModifiedBy(UserUtil.getCode());
        damaged.setModifiedName(partyCache.translate(UserUtil.getCode()));
        if (DamagedStatusEnum.PASS.getValue().equals(damaged.getStatus())) {
            //准备生成发货单
            Delivery delivery = new Delivery();
            // XYTODO TODO 应该在审核前就判断单据状态、数据是否存在，且是从数据库中获取的数据

            Damaged damagedFordelivery = this.getOne(new QueryWrapper<Damaged>().lambda().eq(Damaged::getCode, damaged.getCode()).eq(Damaged::getGroupCode,UserUtil.getBranchCode()));

            BeanUtils.copyProperties(damagedFordelivery, delivery);
            delivery.setCode(OrderIdGeneratorUtil.generatorOrderId(OrderIdGeneratorUtil.OrderTypeEnum.FH, "",UserUtil.getBranchCode()));
            delivery.setSourceCode(damagedFordelivery.getCode());
            delivery.setType(DeliveryTypeEnum.OUT_BAOSUN.getValue());
            delivery.setCreatedBy(UserUtil.getCode());
            delivery.setGmtCreated(LocalDateTime.now());
            delivery.setStatus(DeliveryStatusEnum.UN_DISTRIBUTION.getValue());

            List<DamagedItem> damagedItemList = this.iDamagedItemService.list(new QueryWrapper<DamagedItem>().lambda().eq(DamagedItem::getDamagedCode, damaged.getCode()).eq(DamagedItem::getGroupCode,UserUtil.getBranchCode()));

            List<DeliveryItem> deliveryItemList = new ArrayList<>();

            // 计算明细中商品种数
            Map<String, Boolean> goodsSortMap = new HashMap<>();

            BigDecimal totalNum = BigDecimal.ZERO;
            for (DamagedItem info : damagedItemList) {
                DeliveryItem deliveryItem = new DeliveryItem();

                BeanUtils.copyProperties(info, deliveryItem);
                deliveryItem.setCode(IdUtil.simpleUUID());
                deliveryItem.setDeliveryCode(delivery.getCode());
                deliveryItem.setQuantity(info.getUnitQuantity());
                deliveryItem.setTotalNum(info.getQuantity());
                deliveryItem.setCreatedBy(UserUtil.getCode());
                deliveryItem.setGmtCreated(LocalDateTime.now());
                deliveryItem.setGoodsCode(info.getGoodsCode());
                deliveryItem.setGoodsBarCode(info.getGoodsBarCode());
                deliveryItem.setGoodsUnit(info.getGoodsUnit());
                deliveryItem.setGoodsName(info.getGoodsName());
                deliveryItem.setSourceItemCode(info.getCode());
                deliveryItemList.add(deliveryItem);

                goodsSortMap.put(info.getGoodsCode(), true);

                totalNum = totalNum.add(info.getQuantity());
            }

            // 保存发货单
            delivery.setTotalNum(totalNum);
            delivery.setGoodsSortQuantity(new BigDecimal(Integer.toString(goodsSortMap.size())));
            boolean flag = iDeliveryService.save(delivery);
            //保存发货单明细
            iDeliveryItemService.saveBatch(deliveryItemList);
            if (flag) {
                this.update(damaged, new QueryWrapper<Damaged>().lambda().eq(Damaged::getCode, damaged.getCode()).eq(Damaged::getGroupCode,UserUtil.getBranchCode()));
                return Result.ok("审核通过");
            } else {
                return Result.error("生成发货单失败");
            }
        } else {
            this.update(damaged, new QueryWrapper<Damaged>().lambda().eq(Damaged::getCode, damaged.getCode()).eq(Damaged::getGroupCode,UserUtil.getBranchCode()));
        }
        return Result.ok("审核通过");
    }

    @Override
    public List<DamagedExcelDTO> damagedView(List<DamagedExcelDTO> damagedExcelDTOList) {
        //校验授权仓库code和货主code不能为空
        ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
        String branchCode = UserUtil.getBranchCode();
        // 校验Excel里必填项是否有空值
        validateNotBlank(damagedExcelDTOList);
        // 校验仓库是否相同
        validateSameWarehouse(damagedExcelDTOList);
        // 校验仓库是否启用并且开启库位管理
        validateWarehouseLocationManagement(damagedExcelDTOList, branchCode);
        // 校验货主是否相同 只允许单货主导入
        validateSameShipment(damagedExcelDTOList);
        List<String> authorizeShipmentCodes = UserUtil.getAuthorizeShipmentCodes();
        if (IterUtil.isEmpty(authorizeShipmentCodes)) {
            throw new ServiceException(CommonConst.PLEASE_AUTHORIZE_THE_WAREHOUSE_AND_SHIPMENT_FIRST_AND_THEN_LOG_IN_AGAIN);
        }
        List<Shipment> shipments = shipmentService.list(new QueryWrapper<Shipment>().lambda().in(Shipment::getPartyCode, authorizeShipmentCodes).eq(Shipment::getBranchCode,UserUtil.getBranchCode()));
        // 校验 当前用户授权的仓库、入驻商
        validateAuthorizationWarehouseShipment(damagedExcelDTOList.get(NUM_ZERO).getWarehouseSerialNumber(), damagedExcelDTOList.get(NUM_ZERO).getShipmentSerialNumber(), authorizeShipmentCodes, branchCode);
        // 校验Excel里是否有重复数据
        validateRepeatData(damagedExcelDTOList);

        List<Map<String, Object>> warehouseCacheAll = warehouseCache.getAllByGroupCode(branchCode);
        List<Map<String, Object>> goodsCacheAll = goodsCache.getAllByGroupCode(UserUtil.getBranchCode());
        List<DictCacheDO> dictCacheAll = dictCache.getListByType(DAMAGED_TYPE,UserUtil.getBranchCode());

        IntStream.range(NUM_ZERO, damagedExcelDTOList.size()).forEach(index -> {
            // 验证一些字符长度
            String reason = damagedExcelDTOList.get(index).getReason();
            if (StrUtil.isNotBlank(reason) && StrUtil.length(reason) > TWO_HUNDRED_FIFTY_FIVE.intValue()) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + REASON_NAME + TOO_LONG);
            }
            String remarks = damagedExcelDTOList.get(index).getRemarks();
            if (StrUtil.isNotBlank(remarks) && StrUtil.length(remarks) > TWO_HUNDRED_FIFTY_FIVE.intValue()) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + REMARKS_NAME + TOO_LONG);
            }
            // 校验Excel里的值，在系统中是否存在
            List<Map<String, Object>> warehouseCaches = warehouseCacheAll.stream().filter(item -> damagedExcelDTOList.get(index).getWarehouseSerialNumber().equals(item.get(SERIAL_NUMBER)) &&
                    branchCode.equals(item.get(GROUP_CODE))).collect(Collectors.toList());
            if (CollUtil.isEmpty(warehouseCaches)) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + WAREHOUSE + NOT_EXIST);
            }
            damagedExcelDTOList.get(index).setWarehouseCode((String) warehouseCaches.get(NUM_ZERO).get(CODE));
            damagedExcelDTOList.get(index).setWarehouseName((String) warehouseCaches.get(NUM_ZERO).get(NAME));

            List<Shipment> shipments1 = shipments.stream().filter(item -> damagedExcelDTOList.get(index).getShipmentSerialNumber().equals(item.getPartyCode())).collect(Collectors.toList());
            if (CollUtil.isEmpty(shipments1)) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + SHIPMENT + NOT_EXIST);
            }
            if (!NUM_THREE.equals(shipments1.get(NUM_ZERO).getAuthStatus())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + SHIPMENT + UNAPPROVE_NAME);
            }
//            saas改造货主和承运商没有绑定关系
//            List<Map<String, Object>> warehouseShipmentCacheAll = warehouseShipmentCache.get((String) warehouseCaches.get(NUM_ZERO).get(CODE));
//            List<Map<String, Object>> warehouseShipments = warehouseShipmentCacheAll.stream().filter(item -> item.get(SHIPMENT_CODE).equals(shipments1.get(NUM_ZERO).getPartyCode())).collect(Collectors.toList());
//            if (CollUtil.isEmpty(warehouseShipments)) {
//                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + SHIPMENT_NOT_BELONG_TO_WAREHOUSE);
//            }
            damagedExcelDTOList.get(index).setShipmentCode(shipments1.get(NUM_ZERO).getPartyCode());
            // 企业货主使用企业名做货主名， 其他暂时用企业用户名做货主名

            damagedExcelDTOList.get(index).setShipmentName(shipments1.get(NUM_ZERO).getUserName());

            List<DictCacheDO> dictCacheDOList = dictCacheAll.stream().filter(item -> item.getName().equals(damagedExcelDTOList.get(index).getTypeName())).collect(Collectors.toList());
            if (CollUtil.isEmpty(dictCacheDOList)) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + DAMAGED_TYPE_NAME + NOT_EXIST);
            }
            damagedExcelDTOList.get(index).setType(dictCacheDOList.get(NUM_ZERO).getCode());

            List<Map<String, Object>> goodsCaches = goodsCacheAll.stream().filter(item -> damagedExcelDTOList.get(index).getGoodCode().equals(item.get(GOOD_CODE)) &&
                    shipments1.get(NUM_ZERO).getPartyCode().equals(item.get(SHIPMENT_CODE))).collect(Collectors.toList());
            if (CollUtil.isEmpty(goodsCaches)) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + GOODS + NOT_EXIST);
            }
            if (!StatusEnum.ACTIVE.getValue().equals(goodsCaches.get(NUM_ZERO).get(STATUS))) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + GOODS + NOT_ENABLED);
            }
            damagedExcelDTOList.get(index).setGoodsCode((String) goodsCaches.get(NUM_ZERO).get(CODE));
            damagedExcelDTOList.get(index).setGoodsBarCode((String) goodsCaches.get(NUM_ZERO).get(BAR_CODE));
            damagedExcelDTOList.get(index).setSpec((String) goodsCaches.get(NUM_ZERO).get(SPEC));

            List<GoodsUnitConversion> goodsUnitConversions = goodsUnitConversionCache.get((String) goodsCaches.get(NUM_ZERO).get(CODE));
            List<GoodsUnitConversion> goodsUnitConversionList = goodsUnitConversions.stream().filter(item -> item.getUnitName().equals(damagedExcelDTOList.get(index).getGoodsUnitName())).collect(Collectors.toList());
            if (CollUtil.isEmpty(goodsUnitConversionList)) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + GOODS_UNIT + NOT_EXIST);
            }
            Map<String, Object> unitCacheMap = unitCache.get(goodsUnitConversionList.get(NUM_ZERO).getUnitCode());
            if (!StatusEnum.ACTIVE.getValue().equals(unitCacheMap.get(STATUS))) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + GOODS_UNIT + NOT_ENABLED);
            }
            damagedExcelDTOList.get(index).setGoodsUnit(goodsUnitConversionList.get(NUM_ZERO).getUnitCode());
            damagedExcelDTOList.get(index).setGoodsUnitName(goodsUnitConversionList.get(NUM_ZERO).getUnitName());

            List<GoodsUnitConversion> basicUnitList = goodsUnitConversions.stream().filter(item -> item.getFlag().equals(NUM_ONE)).collect(Collectors.toList());
            damagedExcelDTOList.get(index).setBasicUnit(basicUnitList.get(NUM_ZERO).getUnitCode());
            damagedExcelDTOList.get(index).setBasicUnitName(basicUnitList.get(NUM_ZERO).getUnitName());
            damagedExcelDTOList.get(index).setBasicQuantity(basicUnitList.get(NUM_ZERO).getQuantity());
            damagedExcelDTOList.get(index).setUnitQuantity(new BigDecimal(damagedExcelDTOList.get(index).getDamagedQuantity()));

        });

        damagedCache.initCache(damagedExcelDTOList);
        return damagedExcelDTOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void damagedImport() {
        List<DamagedExcelDTO> damagedExcelDTOList = damagedCache.getCache();
        if (CollUtil.isNotEmpty(damagedExcelDTOList)) {
            Damaged damaged = new Damaged();
            damaged.setCode(OrderIdGeneratorUtil.generatorOrderId(OrderIdGeneratorUtil.OrderTypeEnum.BS, "",UserUtil.getBranchCode()));
            damaged.setWarehouseCode(damagedExcelDTOList.get(NUM_ZERO).getWarehouseCode());
            damaged.setShipmentCode(damagedExcelDTOList.get(NUM_ZERO).getShipmentCode());
            damaged.setGroupCode(UserUtil.getBranchCode());
            damaged.setType(damagedExcelDTOList.get(NUM_ZERO).getType());
            damaged.setWarehouseName(warehouseCache.translate(damaged.getWarehouseCode()));
            damaged.setShipmentName(shipmentCache.translate(damaged.getShipmentCode()));
            damaged.setRemarks(damagedExcelDTOList.get(NUM_ZERO).getReason());
            damaged.setCreatedBy(UserUtil.getCode());
            damaged.setCreatedName(partyCache.translate(UserUtil.getCode()));
            damaged.setStatus("0");

            List<DamagedItem> damagedItemList = damagedExcelDTOList.stream().map(item -> {
                DamagedItem damagedItem = new DamagedItem();
                BeanUtils.copyProperties(item, damagedItem);

                return damagedItem;
            }).collect(Collectors.toList());

            damaged.setDamagedItemList(damagedItemList);
            save(damaged);
            damagedCache.removeCache();
        }
    }

    /**
     * 保存明细
     *
     * @param entity 收货单
     */
    private void saveItem(Damaged entity) {
        entity.getDamagedItemList().forEach(r -> {
            if (StrUtil.isNotBlank(r.getCode())) {
                r.setGroupCode(UserUtil.getBranchCode());
                r.setQuantity(r.getUnitQuantity().multiply(r.getBasicQuantity()));
                r.setModifiedBy(UserUtil.getCode());
                r.setModifiedName(partyCache.translate(UserUtil.getCode()));
            } else {
                r.setGroupCode(UserUtil.getBranchCode());
                r.setCode(IdUtil.simpleUUID());
                r.setDamagedCode(entity.getCode());
                r.setQuantity(r.getUnitQuantity().multiply(r.getBasicQuantity()));
                Map<String, Object> goodsMap = goodsCache.get(r.getGoodsCode());
                r.setSpec((String) goodsMap.get("spec"));
                r.setCreatedBy(entity.getCreatedBy());
                r.setGmtCreated(entity.getGmtCreated());
            }
        });

        // 批量保存或删除明细
        iDamagedItemService.saveOrUpdateBatch(entity.getDamagedItemList());
    }

    /**
     * 校验Excel里必填项是否有空值
     *
     * @param damagedExcelDTOList
     */
    private void validateNotBlank(List<DamagedExcelDTO> damagedExcelDTOList) {
        for(int index = NUM_ZERO; index < damagedExcelDTOList.size(); index++){
            // 校验Excel里必填项是否有空值
            if (StrUtil.isBlank(damagedExcelDTOList.get(index).getWarehouseSerialNumber())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + WAREHOUSE_SERIAL_NUMBER + NOT_BLANK);
            }
            if (StrUtil.isBlank(damagedExcelDTOList.get(index).getWarehouseName())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + WAREHOUSE_NAME + NOT_BLANK);
            }
            if (StrUtil.isBlank(damagedExcelDTOList.get(index).getShipmentSerialNumber())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + SHIPMENT_SERIAL_NUMBER + NOT_BLANK);
            }
            if (StrUtil.isBlank(damagedExcelDTOList.get(index).getShipmentName())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + SHIPMENT_NAME + NOT_BLANK);
            }
            if (StrUtil.isBlank(damagedExcelDTOList.get(index).getTypeName())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + COLLECT_TYPE_NAME + NOT_BLANK);
            }
            if (StrUtil.isBlank(damagedExcelDTOList.get(index).getGoodCode())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + GOOD_CODE_NAME + NOT_BLANK);
            }
            if (StrUtil.isBlank(damagedExcelDTOList.get(index).getGoodsName())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + GOODS_NAME_TEXT + NOT_BLANK);
            }
            if (StrUtil.isBlank(damagedExcelDTOList.get(index).getGoodsUnitName())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + GOODS_UNIT + NOT_BLANK);
            }
            if (StrUtil.isBlank(damagedExcelDTOList.get(index).getDamagedQuantity())) {
                throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + QUANTITY + NOT_BLANK);
            }

        }
    }

    /**
     * 校验是否有重复数据
     *
     * @param damagedExcelDTOList
     */
    private void validateRepeatData(List<DamagedExcelDTO> damagedExcelDTOList) {
        List<DamagedExcelDTO> damagedExcelList = damagedExcelDTOList;
        Stream.iterate(NUM_ZERO, index -> index + NUM_ONE).limit(damagedExcelDTOList.size()).forEach(index -> {
            Stream.iterate(NUM_ZERO, indexJ -> indexJ + NUM_ONE).limit(damagedExcelList.size()).forEach(indexJ -> {
                boolean warehouseFlag = damagedExcelDTOList.get(index).getWarehouseSerialNumber().equals(damagedExcelList.get(indexJ).getWarehouseSerialNumber());
                boolean shipmentFlag = damagedExcelDTOList.get(index).getShipmentSerialNumber().equals(damagedExcelList.get(indexJ).getShipmentSerialNumber());
                boolean goodsFlag = damagedExcelDTOList.get(index).getGoodCode().equals(damagedExcelList.get(indexJ).getGoodCode());
                boolean typeFlag = damagedExcelDTOList.get(index).getTypeName().equals(damagedExcelList.get(indexJ).getTypeName());

                if (warehouseFlag && shipmentFlag && goodsFlag && typeFlag && !index.equals(indexJ)) {
                    throw new ServiceException(TIP_PREFIX + (index + NUM_THREE) + LINE + AND_NAME + TIP_PREFIX + (indexJ + NUM_THREE) + LINE + REPEAT_DATA);
                }
            });
        });
    }

    /**
     * 校验仓库是否相同
     *
     * @param damagedExcelDTOList
     */
    private void validateSameWarehouse(List<DamagedExcelDTO> damagedExcelDTOList) {
        damagedExcelDTOList.forEach(item -> {
            damagedExcelDTOList.forEach(item1 -> {
                if (!item.getWarehouseSerialNumber().equals(item1.getWarehouseSerialNumber())) {
                    throw new ServiceException(EXIST + WAREHOUSE_SERIAL_NUMBER + NOT_SAME + DATA_NAME);
                }
            });
        });
    }

    /**
     * 校验货主是否相同 只允许单货主导入
     * @param damagedExcelDTOList
     */
    private void validateSameShipment(List<DamagedExcelDTO> damagedExcelDTOList) {
        damagedExcelDTOList.forEach(item -> {
            damagedExcelDTOList.forEach(item1 -> {
                if(!item.getShipmentSerialNumber().equals(item1.getShipmentSerialNumber())) {
                    throw new ServiceException(EXIST + SHIPMENT_SERIAL_NUMBER + NOT_SAME + DATA_NAME);
                }
            });
        });
    }

    /**
     * 校验仓库是否启用并且开启库位管理
     * @param damagedExcelDTOList
     * @param branchCode
     */
    private void validateWarehouseLocationManagement(List<DamagedExcelDTO> damagedExcelDTOList, String branchCode) {
        List<Map<String, Object>> warehouseCacheAll = warehouseCache.getAllByGroupCode(branchCode);
        List<Map<String, Object>> warehouseMaps = warehouseCacheAll.stream().filter(item -> item.get(SERIAL_NUMBER).equals(damagedExcelDTOList.get(NUM_ZERO).getWarehouseSerialNumber()) && branchCode.equals(item.get(GROUP_CODE))).collect(Collectors.toList());
        if(CollUtil.isEmpty(warehouseMaps)) {
            throw new ServiceException(WAREHOUSE + NOT_EXIST);
        }
        String status = (String) warehouseMaps.get(NUM_ZERO).get(STATUS);
        if(!StatusEnum.ACTIVE.getValue().equals(status)) {
            throw new ServiceException(WAREHOUSE + NOT_ENABLED);
        }
        Integer locationManagement = (Integer) warehouseMaps.get(NUM_ZERO).get(LOCATION_MANAGEMENT);
        if(!NUM_ONE.equals(locationManagement)) {
            throw new ServiceException(WAREHOUSE + NOT_LOCATION_MANAGEMENT);
        }
    }

    /**
     * 校验 当前用户授权的仓库、入驻商
     * @param warehouseSerialNumber
     * @param shipmentSerialNumber
     * @param branchCode
     */
    private void validateAuthorizationWarehouseShipment(String warehouseSerialNumber, String shipmentSerialNumber, List<String> shipmentsCodes, String branchCode) {

        List<Map<String,Object>> warehouseList = UserUtil.getAuthorizeWarehouseList();
        if(IterUtil.isEmpty(warehouseList)){
            throw new ServiceException(CURRENT_USER_NAME + WITHOUT + WAREHOUSE + PERMISSIONS);
        }


        boolean bool = warehouseList.stream().map(r->
                BeanUtil.toBean(r,Warehouse.class)
        ).map(Warehouse::getGroupCode).filter(s->StrUtil.equals(branchCode,s)).count()>0;

        boolean bool2 = warehouseList.stream().map(r->
                BeanUtil.toBean(r,Warehouse.class)
        ).map(Warehouse::getSerialNumber).filter(s->StrUtil.equals(warehouseSerialNumber,s)).count()>0;

        if (!bool || !bool2) {
            throw new ServiceException(CURRENT_USER_NAME + WITHOUT + WAREHOUSE + LEFT_BRACKET + warehouseSerialNumber + RIGHT_BRACKET + PERMISSIONS);
        }
        if (!shipmentsCodes.contains(shipmentSerialNumber)) {
            throw new ServiceException(CURRENT_USER_NAME + WITHOUT + SHIPMENT + LEFT_BRACKET + shipmentSerialNumber + RIGHT_BRACKET + PERMISSIONS);
        }



    }

}
